package com.ljcalc.business.components;

import java.util.HashMap;

public class Combination {

	protected long[] comb = null;
	private int index = 0;
	private boolean isFull = false;
	private boolean isConsecutiveAcceptableCombination = true;
	private boolean hasSameCombInHistory = false;
	private boolean inTimeConsecutiveTolerance = true;
	
	private boolean similarToHistory = false;
	private HashMap<String, Combination> similarHistoryCombMap = null;
	private int averageSubCombOccurenceTimes  =0 ;
	private boolean isInMinMaxDiffTolerance = true;
	private boolean isInMinMaxMidDiffTolerance = true;;

	public boolean isisConsecutiveAcceptableCombination() {
		return isConsecutiveAcceptableCombination;
	}

	public void setisConsecutiveAcceptableCombination(boolean isConsecutiveAcceptableCombination) {
		this.isConsecutiveAcceptableCombination = isConsecutiveAcceptableCombination;
	}

	public Combination(long[] comb){
		this.comb = comb;
	}
	
	/**
	 * fill up the comb with 0
	 */
	public Combination(){
		
	}
	
	public long[] getComb(){
		return comb;
	}
	
	public void setComb(long[] comb){
		this.comb = comb;
	}
	
	public boolean insertNumber(long n){
		
		if(isFull){
			return false;
		}
		
		//do not allow duplicated number
		if(has(n)){
			return false;
		}
		
		boolean changed = false;
		if(index>0){
			changed = compareAndExchange(n,index);
		}
			
		if(!changed){
			comb[index] = n;		
		}
		
		index++;
		if(index==comb.length){
			isFull = true;
		}
		return true;
	}
	
	private boolean compareAndExchange(long n, int i) {
		if(i-1>=0 && comb[i-1]>n){
			comb[i] = comb[i-1];
			comb[i-1] = n;
			compareAndExchange(n,i-1);
			return true;
		}
		
		return false;
		
	}

	public boolean isFull(){
		return this.isFull;
	}
	
	public String toString(){
		
		String ret = "";
		for(int i=0;i<comb.length;i++){
			ret = ret + " " + comb[i];
		}
		
		ret = !isConsecutiveAcceptableCombination?ret+", NCAC":ret;
		ret = hasSameCombInHistory?ret+", SAME":ret;
		ret = !inTimeConsecutiveTolerance?ret+", OOT":ret;
		ret = this.averageSubCombOccurenceTimes==0?ret:(ret+", :"+this.averageSubCombOccurenceTimes);
		ret = this.isInMinMaxDiffTolerance?ret:(ret+", OMMDIFF :");
		ret = this.isInMinMaxMidDiffTolerance?ret:(ret+", OMMMIDDIFF :");
		
		ret = this.similarToHistory?ret+", \nHS="+similarHistoryCombMap.size():(ret+"\n");

		
		return ret;
	}

	public boolean has(long n) {
		//do not allow duplicated number
		for(int i=0;i<comb.length;i++){
			if(comb[i] == n){
				return true;
			}
			if(comb[i] == 0){
				return false;
			}
		}
		return false;
	}
	
	public boolean equals(Object obj) {
		if(obj instanceof Combination){
			for(int i=0;i<comb.length;i++){
				if(comb[i]!=((Combination)obj).getComb()[i]){
					return false;
				}
			}
			return true;
		}
		return false; 
	}

	public void setHasSameCombInHistory(boolean hasSameCombInHistory) {
		this.hasSameCombInHistory  = hasSameCombInHistory;
		
	}

	public void setInTimeConsecutiveTolerance(boolean inTimeConsecutiveTolerance) {
		this.inTimeConsecutiveTolerance  = inTimeConsecutiveTolerance;
	}
	
	public void setHistorySimilarities(HashMap<String, Combination> hashMap){
		this.similarHistoryCombMap = hashMap;
		if(hashMap!=null&&hashMap.size()>0){
			this.similarToHistory = true;
		}else{
			this.similarToHistory = false;
		}
	}

	public void setAverageSubCombOccurencesTimes(
			int averageSubCombOccurenceTimes) {
		this.averageSubCombOccurenceTimes   = averageSubCombOccurenceTimes;
	}

	public void setIsMinMaxDiffTolerance(boolean inMinMaxDiffTolerance) {
		this.isInMinMaxDiffTolerance  = inMinMaxDiffTolerance;
		
	}

	public void setIsMinMaxMidDiffTolerance(boolean inMinMaxDiffMidTolerance) {
		this.isInMinMaxMidDiffTolerance  = inMinMaxDiffMidTolerance;
		
	}


}
